package com.eshin.autotest.processor;

import org.springframework.aop.framework.autoproxy.AutoProxyUtils;
import org.springframework.aop.scope.ScopedObject;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author Eshin
 * @title: CustomBeanSingletonProcessor
 * @projectName pay
 * @date 2019/6/189:07
 */

/**
 * 参考org.springframework.context.event.EventListenerMethodProcessor
 */

@Component
public class AnnoCustomBeanSingletonProcessor implements SmartInitializingSingleton {

    ApplicationContext context;
    public AnnoCustomBeanSingletonProcessor(ApplicationContext context) {
        this.context = context;
    }

    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("start AnnoCustomBeanSingletonProcessor afterSingletonsInstantiated");
        String[] beans = this.context.getBeanNamesForType(Object.class);

        for (String beanName:beans ) {
            if(beanName.contains("elloConfiguration") && !ScopedProxyUtils.isScopedTarget(beanName)){
                System.out.println(beanName+"------------------------------------");
//                获取@Bean注解的方法，需要在使用了@Bean方法的Configuration类上查找
                Class<?> type = type = AutoProxyUtils.determineTargetClass((ConfigurableListableBeanFactory) this.context.getAutowireCapableBeanFactory(), beanName);
                if(null != type && ScopedObject.class.isAssignableFrom(type)){
                    type = AutoProxyUtils.determineTargetClass((ConfigurableListableBeanFactory) this.context.getAutowireCapableBeanFactory(),
                            ScopedProxyUtils.getTargetBeanName(beanName));
                }
                Map<Method, Bean> annotatedMethods = annotatedMethods = MethodIntrospector.selectMethods(type,
                        new MethodIntrospector.MetadataLookup<Bean>() {
                            @Override
                            public Bean inspect(Method method) {
                                return AnnotatedElementUtils.findMergedAnnotation(method, Bean.class);
                            }
                        });
                annotatedMethods.forEach((key,value)->{
                    System.out.println(key.getName());
                });
            }
        }
        System.out.println("complete AnnoCustomBeanSingletonProcessor afterSingletonsInstantiated");
    }
}
